%%%-------------------------------------------------------------------
%%% @author Rain
%%% @doc 生成proto和cmd协议号关联文件
%%% @end
%%%-------------------------------------------------------------------
-module(build_proto_cmd).
-author("Rain").
-include("build_proto.hrl").

%% API
-export([build/1]).
-export([get_by_cmd_list/0, set_by_cmd_list/1]).
-export([get_by_msg_name_list/0, set_by_msg_name_list/1]).

%% @doc 构建proto和cmd协议号关联文件
build(OutPath) ->
    ProtoCmdFile = filename:join(OutPath, "proto_cmd.erl"),
    {ok, IoDevice} = file:open(ProtoCmdFile, [write]),
    build_header(IoDevice),
    by_msg_name_fun(IoDevice),
    by_cmd_fun(IoDevice),
    file:close(IoDevice),
    io:format("Build Proto CMD Done~n"),
    ok.

base_header() ->
    "%% -*- coding: utf-8 -*-\n"
    "%% Automatically generated, do not edit\n\n"
    "-module(proto_cmd).\n\n"
    "-export([by_msg_name/1, by_cmd/3]).\n\n".


build_header(IoDevice) ->
    io:format(IoDevice, "~s", [base_header()]).

by_msg_name_fun(IoDevice) ->
    List = get_by_msg_name_list(),
    by_msg_name_fun(List, IoDevice).
by_msg_name_fun([], IoDevice) ->
    io:format(IoDevice, "by_msg_name(_) -> undefined.~n~n", []);
by_msg_name_fun([{NameKey, #{pb_mod := _PbMod, cmd_main_id := _CmdMainId,
    cmd_sub_id := _CmdSubId} = V} | T], IoDevice) ->
    io:format(IoDevice, "by_msg_name(~w) -> ~w;~n", [NameKey, V]),
    by_msg_name_fun(T, IoDevice).


by_cmd_fun(IoDevice) ->
    List = get_by_cmd_list(),
    by_cmd_fun(List, IoDevice).
by_cmd_fun([], IoDevice) ->
    io:format(IoDevice, "by_cmd(_, _, _) -> undefined.~n~n", []);
by_cmd_fun([{{CSType, CmdMainId, CmdSubId},
    #{pb_mod := _PbMod, msg_name := _CmdMainId} = V} | T], IoDevice) ->
    io:format(IoDevice, "by_cmd(~w, ~w, ~w) -> ~w;~n", [CSType, CmdMainId, CmdSubId, V]),
    by_cmd_fun(T, IoDevice).


get_by_cmd_list() ->
    case get(get_by_cmd_list) of
        undefined ->
            [];
        Any ->
            Any
    end.

%% CmdKey :: {CSType, CmdMainId, CmdSubId}
%% CSType :: c2s | s2c
%% List :: {CmdKey, #{pb_mod => PbMod, msg_name => MsgName}}
set_by_cmd_list(List) ->
    put(get_by_cmd_list, List).

get_by_msg_name_list() ->
    case get(by_msg_name_list) of
        undefined ->
            [];
        Any ->
            Any
    end.

%% List :: [{NameKey, #{pb_mod => PbMod, cmd_main_id := CmdMainId, cmd_sub_id := CmdSubId}}|...]
set_by_msg_name_list(List) ->
    put(by_msg_name_list, List).